home *** CD-ROM | disk | FTP | other *** search
- //////////////
- // Isam.cpp //
- //////////////
-
- #include "isam.h"
- #include <fstream.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <stdarg.h>
- #include <ctype.h>
-
- static struct BTParms {
- char name[9], filename[9];
- int keylen, dreclen, maxrecs, indxfd, datafd,
- kstart, count;
- t_func keygen;
- } btparms[40];
-
- static int items = 0;
-
- extern "C" {
- int (*Write)(int,const void *,unsigned) = write;
- int (*Read )(int,void *,unsigned) = read;
- }
- static void isam_init(void);
-
- static void isam_init(void)
- {
- ifstream btr("btparms.btr");
- char nwln, item[81], buf[20], fname[13], fcname[9];
- int i;
-
- if (!btr)
- eprintf("\n\nUnable to open btparms.btr.\n");
-
- for (i = 0; i < 40; i++) {
- btr.get (item, 80);
- if (!strlen(item))
- break;
- btr.get(nwln);
- strcpy(btparms[i].name, strtok(item, "^"));
- strtok(NULL, "^");
- strcpy(buf, strtok(NULL, "^"));
- btparms[i].keylen = atoi(buf);
- strtok(NULL, "^");
- strcpy(buf, strtok(NULL, "^"));
- btparms[i].dreclen = atoi(buf);
- strtok(NULL, "^");
- strcpy(fname, strtok(NULL, "^"));
- strtok(NULL, "^");
- strcpy(buf, strtok(NULL, "^"));
- btparms[i].kstart = atoi(buf);
- strcpy(fcname, nospace(strtok(NULL, "^")));
- strcpy(btparms[i].filename, strtok(fname,"."));
- btparms[i].count = 0;
- btparms[i].indxfd = btparms[i].datafd = -1;
- if (strlen(fcname))
- btparms[i].keygen = cataloged_func (
- catalog_number(fcname));
- else
- btparms[i].keygen = (t_func) NULL;
- }
-
- items = i;
- btr.close();
-
- if (!items)
- eprintf("\n\nUnable to initialize isam system.\n");
-
- for (i = items; i < 40; i++) {
- strcpy(btparms[i].name,"");
- strcpy(btparms[i].filename,"");
- btparms[i].keygen = NULL;
- btparms[i].keylen = btparms[i].dreclen =
- btparms[i].count = btparms[i].kstart = 0;
- btparms[i].indxfd = btparms[i].datafd = -1;
- }
- }
-
- Isam::Isam(const char *datafilename, int e)
- {
- int i, j;
- char buf[20];
-
- backingout = 0;
- elements = e;
- if (!items) // this is the first Isam
- isam_init(); // initialize btparms
-
- strcpy(buf, nospace(datafilename));
- indices = 0;
- // find btree params
- for (i = 0; i < items; i++)
- if (!stricmp(buf, btparms[i].filename))
- btr[indices++] = i;
- if (!indices) // couldn't find any, fatal
- eprintf("\n\nCan't find parameters for %s!\n",
- datafilename);
- // set up btree interfaces
- if( !(btc = new BTC [indices]) ||
- !(inames = new char* [indices]) ||
- !(loc = new long [elements]) ||
- !(oldrec = new char* [elements]) ||
- !(rec = new char* [elements]) ||
- !(okey = new char [btparms[*btr].dreclen])||
- !(nkey = new char [btparms[*btr].dreclen]) )
- eprintf("\n\nOut of memory.\n");
- for (i = 0; i < indices; i++) {
- inames[i] = btparms[btr[i]].name;
- btc[i].btvcount = 1;
- if (btrinit(inames[i], btc+i) == ERR)
- eprintf("\n\nCouldn't initialize %s.\n",
- inames[i]);
- btc[i].btmulti = 0; // record locking off
- }
- for (i = 0; i < elements; i++) {
- loc[i] = 0L;
- if (!(oldrec[i] = new char
- [btparms[*btr].dreclen + 1]) ||
- !(rec[i] = new char
- [btparms[*btr].dreclen + 1]) )
- eprintf("\n\nOut of memory.\n");
- }
- if (btparms[*btr].count) { // open files if neccesary
- fd[0] = btparms[*btr].datafd;
- fd[1] = btparms[*btr].indxfd;
- }
- else { // yup, it's neccesary
- strcpy(buf, btparms[*btr].filename);
- strcat(buf, ".dat");
- if ((fd[0]=bt_open(buf, O_RDWR,S_IRDWR)) == ERR)
- eprintf("\n\nCan't open %s.\n", buf);
- strcpy(buf, btparms[*btr].filename);
- strcat(buf, ".idx");
- if ((fd[1]=bt_open(buf, O_RDWR,S_IRDWR)) == ERR)
- eprintf("\n\nCan't open %s.\n", buf);
- btparms[*btr].datafd = fd[0];
- btparms[*btr].indxfd = fd[1];
- }
-
- (btparms[*btr].count)++; // record that we are here
- clear();
- }
-
- Isam::~Isam()
- {
- int i, j;
- // clean up out mess
- for (i = 0; i < indices; i++)
- btrterm(btc+i);
- for (i = 0; i < elements; i++) {
- delete [] oldrec[i];
- delete [] rec[i];
- }
- delete [] btc;
- delete [] inames;
- delete [] loc;
- delete [] oldrec;
- delete [] rec;
- delete [] nkey;
- delete [] okey;
- // if we're last ones out, turn off the lights
- if (!(--(btparms[*btr].count))) {
- close (fd[0]);
- close (fd[1]);
- btparms[*btr].indxfd = -1;
- btparms[*btr].datafd = -1;
- }
- }
-
- int Isam::write ()
- {
- int deltakey, old1, new1, ele, index, result, len,
- start, notfirst;
- t_func fcn;
- if (*loc < 0) // programmer hasn't followed rules
- eprintf ("No writes after gets!");
- for (ele = 0; ele < elements; ele++) {
- old1 = strlen(oldrec[ele]);
- new1 = strlen( rec[ele]);
- if (!(old1 || new1) ||
- !strcmp(oldrec[ele], rec[ele]))
- continue;
- for (index = 0; index < indices; index++) {
- // generate the old and/or new key
- len = btparms[btr[index]].keylen;
- start = btparms[btr[index]].kstart;
- if ((fcn = btparms[btr[index]].keygen) !=
- (t_func) NULL) {
- if (old1)
- strcpy(okey, fcn(oldrec[ele]));
- if (new1)
- strcpy(nkey, fcn( rec[ele]));
- }
- else {
- if (old1)
- strnncpy(okey, oldrec[ele] + start, len);
- if (new1)
- strnncpy(nkey, rec[ele] + start, len);
- }
- deltakey = (!old1||!new1||stricmp(okey,nkey));
-
- if (old1 && deltakey) {
- notfirst = 0;
- while (strlen(okey) >= len) {
- strnncpy(btc[index].btkey, ToUpper(okey),
- len);
- btc[index].btoptype = (new1 || index ||
- notfirst++ || backingout) ? DELTKY
- : DELETE;
- btc[index].btloc = loc[ele];
- result=cbtree(fd[0], fd[1], btc+index);
- if (result != BTCALLOK)
- backout (ele, 'D', index, result);
- strcpy(okey, okey + len);
- }
- }
- if (new1 && deltakey) {
- notfirst = 0;
- while (strlen(nkey) >= len) {
- strnncpy(btc[index].btkey, ToUpper(nkey),
- len);
- btc[index].btoptype = (loc[ele] == 0L) ?
- INSERT : ISRTKY;
- btc[index].btloc = loc[ele];
- result = cbtree(fd[0], fd[1], btc+index);
- if (result == BTCALLOK)
- loc[ele] = btc[index].btloc;
- else
- backout(ele, 'I', index, result);
- strcpy(nkey, nkey + len);
- }
- }
- }
- if (!new1)
- continue;
- if (btseek (fd[0], loc[ele], btc->btdtalen)
- == -1L)
- backout(ele, 'S');
- if (Write(fd[0],rec[ele],(unsigned)btc->btdtalen)
- != btc->btdtalen)
- backout(ele, 'W');
- }
- clear ();
- return 0;
- }
-
- void Isam::backout(int ele,char op,int index,int result)
- { // backs out record add/change/delete on error
- char *trec;
- if (!(trec = new char [btparms[*btr].dreclen]) ||
- backingout) // I quit! Error in error backout!
- eprintf("\n\nBackout error, error type was %c\n",
- backingout);
- if (index >= 0)
- indices = index + 1; // those beyond index are ok
- backingout = op;
- elements = 1;
- strcpy(trec,rec[ele]);
- strcpy(rec[0],oldrec[ele]);
- strcpy(oldrec[0],trec);
- loc[0] = loc[ele];
- write();
- switch (backingout) {
- case 'I':
- eprintf(
- "\n\nINSERT error, element %d, index %s, result %d\n",
- ele, inames[index], result);
- case 'D':
- eprintf(
- "\n\nDELETE error, element %d, index %s, result %d\n",
- ele, inames[index], result);
- case 'S':
- eprintf ("\n\nSeek error, element %d\n", ele);
- case 'W':
- eprintf ("\n\nWrite error, element %d\n", ele);
- }
- }
-
- int Isam::read(const char *key, int ele_limit, int idx,
- int ele)
- {
- int i = 0, j = 0;
-
- if ((ele_limit + ele) > elements)
- eprintf("\n\nNot enough elements!\n");
- free_svkey(btc+idx);
- btc[idx].btoptype = GETALL;
- strcpy(btc[idx].btkey, ToUpper(key));
- btc[idx].btloc = 0L;
- while (cbtree(fd[0], fd[1], btc + idx) == BTCALLOK) {
- while (btc[idx].btrecnum[i-j] != 0L) {
- if (i < ele_limit) {
- loc[i+ele] = btc[idx].btrecnum[i-j];
- btseek(fd[0], loc[i+ele], btc[idx].btdtalen);
- Read (fd[0], rec[i+ele], btc[idx].btdtalen);
- }
- i++;
- if (!((i-j) < btc[idx].btmax))
- break;
- }
- if ((i-j) < btc[idx].btmax)
- break;
- j += btc[idx].btmax;
- }
- for (j = 0; j < ele_limit; j++)
- strcpy(oldrec[j], rec[j]);
- return i;
- }
-
- int Isam::getfirst(int index)
- {
- return getxxx (index, GETFRST);
- }
-
- int Isam::getnext(int index)
- {
- return getxxx (index, GETNXT);
- }
-
- int Isam::getge (char *key, int index)
- {
- *loc = -1;
- btc[index].btoptype = GETGE;
- strcpy(btc[index].btkey, ToUpper(key));
- if (!(cbtree(fd[0], fd[1], btc + index) == BTCALLOK))
- return 0;
- btseek(fd[0], btc[index].btloc, btc[index].btdtalen);
- Read (fd[0], rec[0], btc[index].btdtalen);
- return 1;
- }
-
- int Isam::getxxx(int index, int opt)
- {
- *loc = -1;
- btc[index].btoptype = opt;
- if (!(cbtree(fd[0], fd[1], btc + index) == BTCALLOK))
- return 0;
- btseek(fd[0], btc[index].btloc, btc[index].btdtalen);
- Read (fd[0], rec[0], btc[index].btdtalen);
- return 1;
- }
-
- void Isam::clear()
- {
- int i;
- for (i = 0; i < elements; i++) {
- loc[i] = 0L;
- memset (oldrec[i],'\0', btparms[*btr].dreclen + 1);
- memset ( rec[i],'\0', btparms[*btr].dreclen + 1);
- }
- }
-
- int Isam::keynum (const char *btname)
- {
- int i;
-
- if (!items)
- eprintf("\n\nBtparms not initialized!\n");
- if (indices < 1)
- eprintf("\n\nNo indices.\n");
- for (i = 0; i < indices; i++)
- if (!stricmp(inames[i], nospace(btname)))
- return i;
- eprintf ("\n\nIndex %s not found.\n", btname);
- return -1;
- }
-
- char* nospace(const char *arg)
- {
- static char rtn[80];
- int i, j = 0, k = strlen(arg);
- for (i = 0; i < k; i++)
- if (arg[i] != ' ')
- rtn[j++] = arg[i];
- rtn[j] = '\0';
- return rtn;
- }
-
- int eprintf(const char *format, ... )
- {
- int rtn;
- va_list argptr;
- va_start(argptr, format);
- rtn = vprintf(format, argptr);
- va_end (argptr);
- exit (1);
- return rtn;
- }
-
- char *ToUpper(const char *c)
- {
- static char d[257];
- int i;
-
- for (i = 0; i < 256, c[i] != '\0'; i++)
- d[i] = toupper(c[i]);
- d[i] = '\0';
- return d;
- }
-
- void Isam::reindex(rel_func func)
- {
- char buf[20], cmd[80];
- int tad, i, rlen = btparms[*btr].dreclen, x, y;
- long l;
-
- clear();
- strcpy(buf, btparms[*btr].filename);
- strcat(buf, ".tad");
- if (bt_open(buf, O_RDWR,S_IRDWR) != ERR)
- // I can't cook in a dirty kitchen!
- // Besides that, the last re-index
- // must have failed and I don't know
- // where the real data is, now.
- eprintf("\n\n%s still exists!\n", buf);
- sprintf(cmd, "ren %s.dat %s.tad",
- btparms[*btr].filename, btparms[*btr].filename);
- close (fd[0]);
- system (cmd); // ren .dat to .tad
- if ((tad = bt_open(buf, O_RDWR,S_IRDWR)) == ERR)
- eprintf("\n\nCan't open %s\n", buf);// ren didn't go
- strcpy(buf, btparms[*btr].filename); // recreate .dat
- strcat(buf, ".dat");
- if((fd[0]=bt_open(buf, O_NEW|O_RDWR, S_IRDWR) ) == ERR)
- eprintf ("\n\nCouldn't recreate %s.dat\n",
- btparms[*btr].filename);
- initdat(fd[0], btc); // create file header
- btparms[*btr].datafd = fd[0];
- strcpy(buf, btparms[*btr].filename); // unlink .idx
- strcat(buf, ".idx");
- close (fd[1]);
- unlink (buf);
- for (i = 0; i < indices; i++) {
- btrterm(btc + i); // to btrinit() with no .idx
- if (btrinit(inames[i], btc+i) == ERR)
- eprintf("\n\nCouldn't re-initialize %s.\n",
- inames[i]);
- creatbtr(btc + i);
- }
- for (i = 0; i < indices; i++) { // re-initialize
- btrterm(btc + i);
- if (btrinit(inames[i], btc+i) == ERR)
- eprintf("\n\nCouldn't re-initialize %s.\n",
- inames[i]);
- } // We now have empty datafile and indexfile
- strcpy(buf, btparms[*btr].filename); // re-open .idx
- strcat(buf, ".idx");
- if((fd[1]=bt_open(buf, O_RDWR, S_IRDWR) ) == ERR)
- eprintf ("\n\nCouldn't recreate %s.idx\n",
- btparms[*btr].filename);
- btparms[*btr].indxfd = fd[1];
- clrscr(); // we're ready
- l = 2L; i = 0;
- while (1) {
- if (!(l%10)) {
- if (l < 11L) {
- gotoxy(10,10);
- cprintf("Processing %s location ",
- btparms[*btr].filename);
- x = wherex(); y = wherey();
- }
- gotoxy(x, y);
- cprintf("%ld", l);
- }
- btseek(tad, l++, rlen);
- if (Read (tad, *rec, rlen) == rlen) {
- if (**rec != '~') {
- if (func)
- if (func(*rec))
- continue;
- write();
- i++;
- }
- }
- else
- break;
- }
- printf ("\n\n%d records added.\n", i);
- close (tad);
- strcpy(buf, btparms[*btr].filename);
- strcat(buf, ".tad");
- unlink (buf); // clean kitchen for next time
- }
-
-